package com.netcracker.studportal.server.facade;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

import com.netcracker.studportal.server.model.Exam;
import com.netcracker.studportal.server.model.ExamWithResult;
import com.netcracker.studportal.server.model.Faculty;
import com.netcracker.studportal.server.model.Material;
import com.netcracker.studportal.server.model.Professor;
import com.netcracker.studportal.server.model.Student;
import com.netcracker.studportal.server.model.Subject;
import com.netcracker.studportal.server.model.University;
import com.netcracker.studportal.server.model.User;
import com.netcracker.studportal.server.model.UserType;
import com.netcracker.studportal.server.util.FacadeUtil;
import com.netcracker.studportal.server.util.FactoryDAO;
import com.netcracker.studportal.server.util.FileUtil;

public class FacadeAdmin {
	public static final Logger LOG = Logger.getLogger(FacadeAdmin.class);

	/**
	 * Method for getting the list of universities.
	 * 
	 * @return 
	 * 	JSONArray of JSONObjects in format:
	 *  "univ_id" 	: "value",
	 *  "univ_name" : "value",
	 *  "city" 		: "value";
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 * */
	public String getAllUniversity() {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getAllUniversity' called");
		}
		try {
			Collection<University> universities = FactoryDAO.getUniversityDAO().getAll();

			JSONArray jsonArray = new JSONArray();
			for (University u : universities) {
				jsonArray.add(u.kJSON());
			}

			return jsonArray.toString();

		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));

			return obj.toString();
		}
	}

	/**
	 * Update table Universities
	 * 
	 * @param param: ,univ_name,city
	 * 	JSONObject in format:
	 * 	"univ_id" 	: "value",
	 *  "univ_name" : "value",
	 *  "city" 		: "value";
	 * 
	 * @return 
	 * 	JSONObject in format:
	 * 	"status" : "success"
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 * */
	public String updateFieldUniversity(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'updateFieldUniversity' called with parameters = " + param);
		}
		if (StringUtils.isNotEmpty(param)) {
			try {
				University univ = FacadeUtil.universityParam(param);

				if (univ == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (univ.getId() == null)
					throw new IllegalArgumentException("Id can't be null");
				if (univ.getName() == null || univ.getName().equals(""))
					throw new IllegalArgumentException(
							"University_name can't be null");

				if (univ.getCity() == null || univ.getCity().equals(""))
					throw new IllegalArgumentException("City can't be null");

				University univ2 = FactoryDAO.getUniversityDAO().getById(univ.getId());
				if (univ2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getUniversityDAO().Update(univ);
				
				JSONObject result = new JSONObject();
				result.put("status", "success");
				return result.toJSONString();
			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		
		return null;
	}

	/**
	 * Delete row from table Universities
	 * 
	 * @param String
	 *            param: univ_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String deleteFieldUniversity(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'deleteFieldUniversity' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				University univ = FacadeUtil.universityParam(param);

				if (univ == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (univ.getId() == null)
					throw new IllegalArgumentException("Id can't be null");

				University univ2 = null;
				try {
					univ2 = FactoryDAO.getUniversityDAO().getById(univ.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (univ2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getUniversityDAO().Delete(univ);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Add row into table Universities
	 * 
	 * @param String
	 *            param: univ_id,univ_name,city
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String addNewUniversity(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'insertIntoUniversity' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {

				University univ = FacadeUtil.universityParam(param);
                
				if (univ == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (univ.getName() == null || univ.getName().equals(""))
					throw new IllegalArgumentException(
							"University_name can't be null");

				if (univ.getCity() == null || univ.getCity().equals(""))
					throw new IllegalArgumentException("City can't be null");

				FactoryDAO.getUniversityDAO().Add(univ);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Method for getting the list of materials.
	 * 
	 * @return 
	 * 	JSONOArray of JSONObject in format:
	 * 	"material_id" : "value",
	 * 	"exam_id" : "value",
	 * 	"material_name" : "value",
	 * 	"material_path" : "value";
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 * */
	public String getAllMaterials() {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getAllMaterials' called");
		}
		try {
			Collection<Material> materials = FactoryDAO.getMaterialDAO().getAll();
			JSONArray jsonArray = new JSONArray();
			for (Material m : materials) {
				JSONObject json = m.kJSON();				
				//String pathToFile = m.getPath();
				//String encodedFile = FileUtil.loadAndEncodeFile(pathToFile);
				json.put("material_path", m.getPath());				
				jsonArray.add(json);
			}

			return jsonArray.toString();
		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Delete row from table Materials
	 * 
	 * @param String
	 *            param: material_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String deleteFieldMaterial(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'deleteFieldMaterial' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Material material = FacadeUtil.materialParam(param);

				if (material == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (material.getId() == null)
					throw new IllegalArgumentException("Id can't be null");

				Material material2 = null;
				try {
					material2 = FactoryDAO.getMaterialDAO().getById(
							material.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (material2 == null)
					throw new Exception("This row doesn't exist");

				FileUtil.deleteFile(material2.getPath());
				
				FactoryDAO.getMaterialDAO().Delete(material);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Method for adding new material by exam.
	 * 
	 * @param param
	 * 	JSONObject in format: 
	 *  "exam_id"		: "value",
	 *  "material_name"	: "value",
	 *  "material_file"	: "value";
	 * 
	 * @return 
	 * 	JSONObject in format:
	 * 	"status" : "success"
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 *  */
	public String addNewMaterial(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'addNewMaterial' called with parameters = " + param);
		}
		try {
			String[] expectedKeys = new String[]{"exam_id", "material_name", "material_file"};
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, expectedKeys);

			String materialFile = inputParams.get("material_file");
			String materialName = inputParams.get("material_name");
			String pathToFile = FileUtil.decodeAndSaveFile(materialFile, materialName);	
			
			Material material = new Material();
			Exam exam = new Exam();
			exam.setId(Long.parseLong(inputParams.get("exam_id")));
			material.setExam(exam);
			material.setName(materialName);
			material.setPath(pathToFile);

			FactoryDAO.getMaterialDAO().Add(material);

			JSONObject result = new JSONObject();
			result.put("status", "success");
			return result.toJSONString();
		} catch (Exception e) {
			LOG.error("Error: ", e);
			
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Return list of Subjects
	 * 
	 * @return String of JSON: subject_id,name,hours,course,description
	 * 
	 *         In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String getAllSubject() {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getAllSubject' called");
		}
		try {
			List<Subject> subject = (List<Subject>) FactoryDAO.getSubjectDAO()
					.getAll();
			JSONArray list = new JSONArray();
			for (Subject s : subject) {
				list.add(s.kJSON());
			}

			String result = null;
			result = list.toString();
			return result;

		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Update table Subjects
	 * 
	 * @param String
	 *            param: subject_id,name,hours,course,description
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String updateFieldSubject(String param) throws Exception {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'updateFieldSubject' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Subject subj = FacadeUtil.subjectyParam(param);

				if (subj == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (subj.getId() == null)
					throw new IllegalArgumentException("Id can't be null");
				if (subj.getName() == null || subj.getName().equals(""))
					throw new IllegalArgumentException(
							"Subject_name can't be null");

				if (subj.getHours() == null)
					throw new IllegalArgumentException("Hours can't be null");

				if (subj.getCourse() == null)
					throw new IllegalArgumentException("Course can't be null");

				Subject subj2 = null;
				try {
					subj2 = FactoryDAO.getSubjectDAO().getById(subj.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (subj2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getSubjectDAO().Update(subj);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Delete row from table Subjects
	 * 
	 * @param String
	 *            param: subject_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String deleteFieldSubject(String param) throws Exception {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'deleteFieldSubject' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Subject subj = FacadeUtil.subjectyParam(param);

				if (subj == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (subj.getId() == null)
					throw new IllegalArgumentException("Id can't be null");

				Subject subj2 = null;
				try {
					subj2 = FactoryDAO.getSubjectDAO().getById(subj.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (subj2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getSubjectDAO().Delete(subj);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Method for adding new subject.
	 * 
	 * @param param
	 * 	JSONObject in format: 
	 *  "name"			: "value",
	 *  "description" 	: "value",
	 *  "course"		: "value",
	 *  "hours"			: "value";
	 * 
	 * @return 
	 * 	JSONObject in format:
	 * 	"status" : "success"
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 * */
	public String addNewSubject(String param) throws Exception {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'addNewSubject' called with parameters = " + param);
		}
		try {
			Subject subject=FacadeUtil.subjectyParam(param);
			
			if (subject.getName() == null)
				throw new IllegalArgumentException("Name can't be null");
			if (subject.getCourse()== null)
				throw new IllegalArgumentException("Course can't be null");
			if (subject.getHours()== null)
				throw new IllegalArgumentException("Hours can't be null");
			
			FactoryDAO.getSubjectDAO().Add(subject);
			
			JSONObject result = new JSONObject();
			result.put("status", "success");
			return result.toJSONString();
		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Return list of Faculties
	 * 
	 * @return String of JSON: faculty_id,faculty_name,univ_id,univ_name,city
	 * 
	 *         In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String getAllFaculty() {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getAllFaculty' called");
		}
		try {
			List<Faculty> faculty = (List<Faculty>) FactoryDAO.getFacultyDAO()
					.getAll();
			JSONArray list = new JSONArray();
			for (Faculty f : faculty) {
				list.add(f.kJSON());
			}

			String result = null;
			result = list.toString();
			return result;

		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Update table Faculties
	 * 
	 * @param String
	 *            param: faculty_id,faculty_name,univ_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String updateFieldFaculty(String param) throws Exception {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'updateFieldFaculty' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Faculty f = FacadeUtil.facultyParam(param);

				if (f == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (f.getId() == null)
					throw new IllegalArgumentException("Id can't be null");
				if (f.getName() == null || f.getName().equals(""))
					throw new IllegalArgumentException(
							"Faculty_name can't be null");

				if (f.getUniversity() == null)
					throw new IllegalArgumentException(
							"University_id can't be null");
				else if (f.getUniversity().getId() == null)
					throw new IllegalArgumentException(
							"University_id can't be null");

				Faculty f2 = null;
				try {
					f2 = FactoryDAO.getFacultyDAO().getById(f.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (f2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getFacultyDAO().Update(f);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Delete row from table Faculty
	 * 
	 * @param String
	 *            param: faculty_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String deleteFieldFaculty(String param) throws Exception {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'deleteFieldFaculty' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Faculty f = FacadeUtil.facultyParam(param);

				if (f == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (f.getId() == null)
					throw new IllegalArgumentException("Id can't be null");

				Faculty f2 = null;
				try {
					f2 = FactoryDAO.getFacultyDAO().getById(f.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (f2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getFacultyDAO().Delete(f);
			
			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Add row into table Faculties
	 * 
	 * @param String
	 *            param: faculty_name,univ_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String addNewFaculty(String param) throws Exception {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'addNewFaculty' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {

				Faculty f = FacadeUtil.facultyParam(param);

				if (f == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");
                  
				if (f.getName() == null || f.getName().equals(""))
					throw new IllegalArgumentException(
							"Faculty_name can't be null");

				if (f.getUniversity() == null)
					throw new IllegalArgumentException(
							"University_id can't be null");
				else if (f.getUniversity().getId() == null)
					throw new IllegalArgumentException(
							"University_id can't be null");

				FactoryDAO.getFacultyDAO().Add(f);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Return list of Professors
	 * 
	 * @return String of JSON:
	 *         prof_id,first_name,patronymic,last_name,birthday,note,
	 *         univ_id,univ_name,city.
	 * 
	 *         In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String getAllProfessor() {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getAllProfessor' called");
		}
		try {
			List<Professor> prof = (List<Professor>) FactoryDAO
					.getProfessorDAO().getAll();
			JSONArray list = new JSONArray();
			for (Professor p : prof) {
				list.add(p.kJSON());
			}

			String result = null;
			result = list.toString();
			return result;
		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Update table Professors Required date format "dd.MM.yyyy"
	 * 
	 * @param String
	 *            param:
	 *            prof_id,first_name,last_name,birthday,univ_id,patronymic,note
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String updateFieldProfessor(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'updateFieldProfessor' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Professor prof = FacadeUtil.professorParam(param);

				if (prof == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (prof.getId() == null)
					throw new IllegalArgumentException("Id can't be null");
				if (prof.getFirst_name() == null
						|| prof.getFirst_name().equals(""))
					throw new IllegalArgumentException(
							"First_name can't be null");
				if (prof.getLast_name() == null
						|| prof.getLast_name().equals(""))
					throw new IllegalArgumentException(
							"Last_name can't be null");
				if (prof.getBirthday() == null)
					throw new IllegalArgumentException("Birthday can't be null");
				if (prof.getUniversity() == null)
					throw new IllegalArgumentException(
							"University_id can't be null");
				else if (prof.getUniversity().getId() == null)
					throw new IllegalArgumentException(
							"Don't update university_id to null");

				Professor prof2 = null;
				try {
					prof2 = FactoryDAO.getProfessorDAO().getById(prof.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (prof2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getProfessorDAO().Update(prof);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Delete row from table Professors
	 * 
	 * @param String
	 *            param: prof_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String deleteFieldProfessor(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'deleteFieldProfessor' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Professor prof = FacadeUtil.professorParam(param);
				if (prof == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");
				if (prof.getId() == null)
					throw new IllegalArgumentException("Id can't be null");

				Professor prof2 = null;
				try {
					prof2 = FactoryDAO.getProfessorDAO().getById(prof.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (prof2 == null)
					throw new Exception("This row doesn't exist");

				User user=new User();
				user.setId(prof.getId());
				FactoryDAO.getUsersDAO().DeleteUser(user);;

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Method for adding new professor.
	 * 
	 * @param param
	 * 	JSONObject in format:
	 * 	"prof_id" 		: "value",
	 * 	"login"			: "value",
	 * 	"password"		: "value",
	 * 	"first_name"	: "value",
	 * 	"patronymic"	: "value"
	 * 	"last_name"		: "value",
	 * 	"birthday"		: "value",
	 * 	"univ_id"		: "value",
	 * 	"note"			: "value";
	 * 
	 * @return 
	 * 	JSONObject in format:
	 * 	"status" : "success"
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 * */
	public String addNewProfessor(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'addNewProfessor' called with parameters = " + param);
		}
		try {
			String[] expectedKeys = new String[]{"login", "password"};
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, expectedKeys);
			
			Professor professor =FacadeUtil.professorParam(param);
			
			if (professor == null)
				throw new IllegalArgumentException(
						"Parameter not meet the requirements");

			if (StringUtils.isEmpty(professor.getFirst_name()))
				throw new IllegalArgumentException("First_name can't be null");
			
			if (StringUtils.isEmpty(professor.getLast_name()))
				throw new IllegalArgumentException("Last_name can't be null");
			
			if(professor.getBirthday()==null) throw new IllegalArgumentException("Birthday can't be null");
			
			if(professor.getUniversity()==null) throw new IllegalArgumentException("University_id can't be null");
			else if(professor.getUniversity().getId()==null) throw new IllegalArgumentException("University_id can't be null");
			
			String login = inputParams.get("login");
			String password = inputParams.get("password");
			User user = FactoryDAO.getUsersDAO().getUserByLoginPass(login, password);
			if (user == null) {
				// such user is not exist yet - create it
				user = new User();
				user.setLogin(login);
				if(professor.getId()!=null) user.setId(professor.getId());
				user.setType(UserType.PROFESSOR.getType());
				FactoryDAO.getUsersDAO().Add(user, password);
				
			} else throw new RuntimeException(
					"This user already exists. Login and password must be unique");
			
			User user2=FactoryDAO.getUsersDAO().getUserByLoginPass(login, password);
			
			if(user2==null) throw new RuntimeException("Error of add user");
			if(user2.getId()==null) throw new RuntimeException("Failed to get the user");
			
			professor.setId(user2.getId());
			
			FactoryDAO.getProfessorDAO().Add(professor);
			
			JSONObject result = new JSONObject();
			result.put("status", "success");
			return result.toJSONString();
		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Return list of Users
	 * 
	 * @return String of JSON:
	 *         user_id,type,login,stud_first_name,stud_last_name,
	 *         prof_first_name,patronymic,prof_last_name
	 * 
	 *         In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String getAllUser() {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getAllUser' called");
		}
		try {
			List<User> user = (List<User>) FactoryDAO.getUsersDAO().getAll();
			JSONArray list = new JSONArray();
			for (User u : user) {
				list.add(u.kJSON());
			}

			String result = null;
			result = list.toString();
			return result;
		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Update table Users
	 * 
	 * @param String
	 *            param: user_id,password
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String updateFieldUser(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'updateFieldUser' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				JSONParser parser = new JSONParser();
				Object o = parser.parse(param);
				JSONObject jsonObj = (JSONObject) o;
				User user = FacadeUtil.userParam(param);
				String str = null;

				if (jsonObj.containsKey("password"))
					str = ((String) jsonObj.get("password"));

				if (user == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (user.getId() == null)
					throw new IllegalArgumentException("Id can't be null");
				if (str == null || str.equals(""))
					throw new IllegalArgumentException("Password can't be null");

				User user2 = null;
				try {
					user2 = FactoryDAO.getUsersDAO().getById(user.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (user2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getUsersDAO().updateUserPassword(user, str);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Delete row from table Users
	 * 
	 * @param String
	 *            param: user_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 */
	public String deleteFieldUser(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'deleteFieldUser' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				User user = FacadeUtil.userParam(param);

				if (user == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (user.getId() == null)
					throw new IllegalArgumentException("Id can't be null");

				User user2 = null;
				try {
					user2 = FactoryDAO.getUsersDAO().getById(user.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (user2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getUsersDAO().DeleteUser(user);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Add row into table Users
	 * 
	 * @param String
	 *            param: user_id,type,login,password
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 */
	public String addNewUser(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'insertIntoUser' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				JSONParser parser = new JSONParser();
				Object o = parser.parse(param);
				JSONObject jsonObj = (JSONObject) o;
				User user = FacadeUtil.userParam(param);
				String str = null;

				if (jsonObj.containsKey("password"))
					str = ((String) jsonObj.get("password"));

				if (user == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");
				
				if (user.getLogin() == null || user.getLogin().equals(""))
					throw new IllegalArgumentException("Login can't be null");
				if (user.getType() == null || user.getType().equals(""))
					throw new IllegalArgumentException("Type can't be null");
				if (str == null || str.equals(""))
					throw new IllegalArgumentException("Password can't be null");

				FactoryDAO.getUsersDAO().Add(user, str);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Return list of Exams Date format "dd.MM.yyyy hh:mm"
	 * 
	 * @return String of JSON:
	 *         exam_id,subject_id,subject_name,exam_date,type,prof_id
	 *         ,prof_first_name, patronymic,prof_last_name
	 * 
	 *         In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 */
	public String getAllExam() {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getAllExam' called");
		}
		try {
			List<Exam> exam = (List<Exam>) FactoryDAO.getExamDAO().getAll();
			JSONArray list = new JSONArray();
			for (Exam ex : exam) {
				list.add(ex.kJSON());
			}

			String result = null;
			result = list.toString();
			return result;
		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Update table Exams Date format "dd.MM.yyyy hh:mm"
	 * 
	 * @param String
	 *            param: exam_id,subject_id,exam_date,type,prof_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 */
	public String updateFieldExam(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'updateFieldExam' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {

				Exam exam = FacadeUtil.examParam(param);

				if (exam == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (exam.getId() == null)
					throw new IllegalArgumentException("Id can't be null");
				if (exam.getSubject() == null)
					throw new IllegalArgumentException(
							"Subject_id can't be null");
				else if (exam.getSubject().getId() == null)
					throw new IllegalArgumentException(
							"Subject_id can't be null");

				if (exam.getExam_date() == null)
					throw new IllegalArgumentException(
							"Exam_date can't be null");

				if (exam.getProfessor() == null)
					throw new IllegalArgumentException(
							"Professor_id can't be null");
				else if (exam.getProfessor().getId() == null)
					throw new IllegalArgumentException(
							"Professor_id can't be null");

				Exam exam2 = null;
				try {
					exam2 = FactoryDAO.getExamDAO().getById(exam.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (exam2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getExamDAO().Update(exam);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));

				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Delete row from table Exams
	 * 
	 * @param String
	 *            param: exam_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 */
	public String deleteFieldExam(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'deleteFieldExam' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Exam exam = FacadeUtil.examParam(param);

				if (exam == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (exam.getId() == null)
					throw new IllegalArgumentException("Id can't be null");

				Exam exam2 = null;
				try {
					exam2 = FactoryDAO.getExamDAO().getById(exam.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (exam2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getExamDAO().Delete(exam);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Add row into table Exams Date format "dd.MM.yyyy hh:mm"
	 * 
	 * @param String
	 *            param: exam_id,subject_id,exam_date,type,prof_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String addNewExam(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'insertIntoExam' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {

				Exam exam = FacadeUtil.examParam(param);

				if (exam == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (exam.getSubject() == null)
					throw new IllegalArgumentException(
							"Subject_id can't be null");
				else if (exam.getSubject().getId() == null)
					throw new IllegalArgumentException(
							"Subject_id can't be null");

				if (exam.getExam_date() == null)
					throw new IllegalArgumentException(
							"Exam_date can't be null");

				if (exam.getProfessor() == null)
					throw new IllegalArgumentException(
							"Professor_id can't be null");
				else if (exam.getProfessor().getId() == null)
					throw new IllegalArgumentException(
							"Professor_id can't be null");

				FactoryDAO.getExamDAO().Add(exam);
				JSONObject obj = new JSONObject();
				obj.put("status", "success");
				return obj.toJSONString();
			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));

				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Return list of ExamWithResult
	 * 
	 * @return String of JSON:
	 *         exam_id,student_id,mark,note,exam{exam_id,subject_id,
	 *         subject_name,exam_date,type,prof_id,prof_first_name,
	 *         patronymic,prof_last_name}
	 * 
	 *         In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 */
	public String getAllExamWithResult() {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getAllExamWithResult' called");
		}
		try {
			List<ExamWithResult> exam = (List<ExamWithResult>) FactoryDAO
					.getExamWithResultDAO().getAll();
			JSONArray list = new JSONArray();
			for (ExamWithResult ex : exam) {
				list.add(ex.kJSON());
			}

			String result = null;
			result = list.toString();
			return result;
		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Update table Exam_results
	 * 
	 * @param String
	 *            param: exam_id,student_id,mark,note
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String updateFieldExamWithResult(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'updateFieldExamWithResult' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				ExamWithResult exam_res = FacadeUtil.examWithResultParam(param);

				if (exam_res == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (exam_res.getExam_id() == null)
					throw new IllegalArgumentException("Id can't be null");
				if (exam_res.getStudent_id() == null)
					throw new IllegalArgumentException(
							"Student_id can't be null");

				ExamWithResult exam_res2 = null;
				try {
					exam_res2 = FactoryDAO.getExamWithResultDAO().getById(
							exam_res.getExam_id(), exam_res.getStudent_id());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (exam_res2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getExamWithResultDAO().Update(exam_res);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Delete row from table Exam_results
	 * 
	 * @param String
	 *            param: exam_id,student_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String deleteFieldExamWithResult(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'deleteFieldExamWithResult' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				ExamWithResult exam_res = FacadeUtil.examWithResultParam(param);

				if (exam_res == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (exam_res.getExam_id() == null
						|| exam_res.getStudent_id() == null)
					throw new IllegalArgumentException("Id can't be null");

				ExamWithResult exam_res2 = null;
				try {
					exam_res2 = FactoryDAO.getExamWithResultDAO().getById(
							exam_res.getExam_id(), exam_res.getStudent_id());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (exam_res2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getExamWithResultDAO().Delete(exam_res);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Add row in table Exam_results
	 * 
	 * @param String
	 *            param: exam_id,student_id,mark,note
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String addNewExamWithResult(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'insertIntoExamWithResult' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {

				ExamWithResult exam_res = FacadeUtil.examWithResultParam(param);

				if (exam_res == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (exam_res.getExam_id() == null)
					throw new IllegalArgumentException("Id can't be null");
				if (exam_res.getStudent_id() == null)
					throw new IllegalArgumentException(
							"Student_id can't be null");

				FactoryDAO.getExamWithResultDAO().Add(exam_res);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Return list of Students DateFormat("dd.MM.yyyy")
	 * 
	 * @return String of JSON:
	 *         student_id,stud_first_name,stud_last_name,birthday
	 *         ,course,faculty_id, faculty_name,group_num;exam_id,note,
	 *         ExamWithResult:{exam_id,student_id,mark,note;
	 *         exam{exam_id,subject_id
	 *         ,subject_name,exam_date,type,prof_id,prof_first_name,
	 *         patronymic,prof_last_name}
	 * 
	 *         } In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String getAllStudent() {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getAllStudent' called");
		}
		try {
			List<Student> student = (List<Student>) FactoryDAO.getStudentDAO()
					.getAll();
			JSONArray list = new JSONArray();
			for (Student st : student) {
				list.add(st.kJSON());
			}

			String result = null;
			result = list.toString();
			return result;
		} catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}

	/**
	 * Update table Students Date Format "dd.MM.yyyy"
	 * 
	 * @param String
	 *            param:
	 *            student_id,stud_first_name,stud_last_name,birthday,course
	 *            ,faculty_id, group_num,note
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String updateFieldStudent(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'updateFieldStudent' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Student stud = FacadeUtil.studentParam(param);

				if (stud == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (stud.getId() == null)
					throw new IllegalArgumentException("Id can't be null");
				if (stud.getFirst_name() == null
						|| stud.getFirst_name().equals(""))
					throw new IllegalArgumentException(
							"First_name can't be null");

				if (stud.getLast_name() == null
						|| stud.getLast_name().equals(""))
					throw new IllegalArgumentException(
							"Last_name can't be null");

				if (stud.getCourse() == null)
					throw new IllegalArgumentException("Course can't be null");

				if (stud.getFaculty() == null)
					throw new IllegalArgumentException(
							"Faculty_id can't be null");
				else if (stud.getFaculty().getId() == null)
					throw new IllegalArgumentException(
							"Faculty_id can't be null");

				if(stud.getGroup_num()==null) throw new IllegalArgumentException(
						"Group_num can't be null");
				
				Student stud2 = null;
				try {
					stud2 = FactoryDAO.getStudentDAO().getById(stud.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (stud2 == null)
					throw new Exception("This row doesn't exist");

				FactoryDAO.getStudentDAO().Update(stud);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Delete row from table Students
	 * 
	 * @param String
	 *            param: student_id
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String deleteFieldStudent(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'deleteFieldStudent' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				Student stud = FacadeUtil.studentParam(param);

				if (stud == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (stud.getId() == null)
					throw new IllegalArgumentException("Id can't be null");

				Student stud2 = null;
				try {
					stud2 = FactoryDAO.getStudentDAO().getById(stud.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}

				if (stud2 == null)
					throw new Exception("This row doesn't exist");

				User user=new User();
				user.setId(stud.getId());
				
				FactoryDAO.getUsersDAO().DeleteUser(user);

			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}

	/**
	 * Add row into table Students Date Format "dd.MM.yyyy"
	 * 
	 * @param String
	 *            param: user_id,login,password
	 *            stud_first_name,stud_last_name,birthday,course,faculty_id,
	 *            group_num,note
	 * 
	 * @return In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String addNewStudent(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'addNewStudent' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {
				JSONParser parser = new JSONParser();
				Object o = parser.parse(param);
				JSONObject jsonObj = (JSONObject) o;
				User user = FacadeUtil.userParam(param);
				Student stud = FacadeUtil.studentParam(param);
				String str = null;

				if (jsonObj.containsKey("password"))
					str = ((String) jsonObj.get("password"));

				if (user == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");
				if (user.getLogin() == null || user.getLogin().equals(""))
					throw new IllegalArgumentException("Login can't be null");
				if (str == null || str.equals(""))
					throw new IllegalArgumentException("Password can't be null");
				user.setType("student");

				if (stud == null)
					throw new IllegalArgumentException(
							"Parameter not meet the requirements");

				if (stud.getFirst_name() == null
						|| stud.getFirst_name().equals(""))
					throw new IllegalArgumentException(
							"First_name can't be null");

				if (stud.getLast_name() == null
						|| stud.getLast_name().equals(""))
					throw new IllegalArgumentException(
							"Last_name can't be null");

				if (stud.getCourse() == null)
					throw new IllegalArgumentException("Course can't be null");

				if (stud.getFaculty() == null)
					throw new IllegalArgumentException(
							"Faculty_id can't be null");
				else if (stud.getFaculty().getId() == null)
					throw new IllegalArgumentException(
							"Faculty_id can't be null");
				
				if(stud.getGroup_num()==null) throw new IllegalArgumentException(
						"Group_num can't be null");
							
				User user2 = null;
				user2 = FactoryDAO.getUsersDAO().getUserByLoginPass(
						user.getLogin(), str);

				if (user2 != null)
					throw new Exception(
							"This user already exists. Login and password must be unique");

				FactoryDAO.getUsersDAO().Add(user, str);

				user = FactoryDAO.getUsersDAO().getUserByLoginPass(
						user.getLogin(), str);

				if (user == null)
					throw new Exception("Error of inserting user");
				stud.setId(user.getId());

				if (stud.getId() == null)
					throw new IllegalArgumentException(
							"Error of inserting student.Student_id not found");

				FactoryDAO.getStudentDAO().Add(stud);
				JSONObject obj = new JSONObject();
				obj.put("status", "success");
				return obj.toJSONString();
			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
	
				return obj.toString();
			}
		}
		return null;
	}
	
	/**
	 * Get list of groups (with numbers of course) for corresponding faculty
	 *  
	 * @param param
	 * JSONObject in format: 
	 * "faculty_id"  :  "value"
	 * 
	 * @return
	 * JSONArray of JSONObject in format:
	 * "group_num"  :  "value"
	 * "course"  :  "value"
	 * 
	 *  In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 */
	public String getGroupsByFaculty(String param){
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getGroupsByFaculty' called with parameters = " + param);
		}
		try{
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"faculty_id"});
			Long faculty_id = Long.parseLong(inputParams.get("faculty_id"));
			
			List<Map<String,String>> m_list = FactoryDAO.getStudentDAO().getGroupsByFaculty(faculty_id);
			
			JSONArray j_list = new JSONArray();
			if (m_list != null && m_list.size() > 0) {
				for(Map<String,String> map : m_list) {
					JSONObject jsonObj=new JSONObject();
					jsonObj.put("group_num", map.get("group_num"));
					jsonObj.put("course", map.get("course"));
					
					j_list.add(jsonObj);			
				}
				String result = j_list.toString();
				return result;
			}else{
				return new JSONArray().toString();
			}	
		}catch (Exception e) {
			LOG.error("Error: ", e);

			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));

			return obj.toString();
		}
	}

	/**
	 * Add exam to students by course and group.
	 * 
	 * @param String
	 *            param: exam_id,course,group_num,faculty_id
	 *            
	 * @return 	 
	 * 	JSONObject in format:
	 * 	"status" : "success"
	 * 
	 * In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String addExamToStudentsGroup(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'addExamToStudentsGroup' called with parameters = " + param);
		}
		if (param != null && !param.equals("")) {
			try {

				Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"exam_id","course","group_num","faculty_id"});
				
				Long examID = Long.parseLong(inputParams.get("exam_id"));			
				Integer course = Integer.parseInt(inputParams.get("course"));				
				Integer group_num = Integer.parseInt(inputParams.get("group_num"));
				Long facultyID = Long.parseLong(inputParams.get("faculty_id"));

				FactoryDAO.getStudentDAO().AddExamToStudentGroup(examID, course, group_num,facultyID);

				JSONObject result = new JSONObject();
				result.put("status", "success");
				return result.toJSONString();
				
			} catch (Exception e) {
				LOG.error("Error: ", e);

				JSONObject obj = new JSONObject();
				obj.put("error", e.getMessage());
				obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
				return obj.toString();
			}
		}
		return null;
	}
	
	
	/**
	 * Get exams by subject.
	 * 
	 * @param String
	 *            param: subject_id
	 *            
	 * @return 	 
	 *  JSONArray of JSONObject in format:
	 *  "exam_id" 			: "value",
	 *  "subject_id" 		: "value",
	 * 	"subject_name" 		: "value",
	 * 	"exam_date" 		: "value",
	 *  "type"              : "value",
	 * 	"prof_id" 			: "value",
	 * 	"prof_first_name" 	: "value",
	 * 	"patronymic" 		: "value",
	 * 	"prof_last_name" 	: "value";
	 * 
	 * In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String getExamsBySubject(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getExamsBySubject' called with parameters = " + param);
		}
		
		try {
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"subject_id"});
			
			Long subjectID = Long.parseLong(inputParams.get("subject_id"));
				
			Collection<Exam> exams = FactoryDAO.getExamDAO().getExamBySubject(subjectID);
			if(exams != null && exams.size() > 0) {
				JSONArray list = new JSONArray();
				for(Exam e : exams) {
					list.add(e.kJSON());
				}	
				String result = list.toString();
				
				return result;
			} else {
				// return empty JSON array, because subject doesn't have any exams
				return new JSONArray().toString();
			}
		} catch (Exception e) {
			LOG.error("Error: ", e);
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
			return obj.toString();
		}
	}
	
	/**
	 * Get list of exams by professor
	 * 
	 * @param param
	 * 	JSONObject in format:
	 * 	"prof_id" : "value";
	 * 
	 * 
	 * @return 
	 * 	JSONArray of JSONObject in format:
	 *  "subject_name" 	: "value",
	 *  "subject_id" 	: "value",
	 *  "exam_id" 		: "value",
	 *  "prof_id" : "value",
	 *  "prof_first_name" : "value",
	 *  "patronymic" : "value",
	 *  "prof_last_name" : "value",
	 *  "type" : "value";
	 *  "exam_date" : "value";
	 *  
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 */
	public String getExamsByProfessor(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getExamsByProfessor' called with parameters = " + param);
		}
		try {
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"prof_id"});
				
			Long profID = Long.parseLong(inputParams.get("prof_id"));
				
			Professor prof = FactoryDAO.getProfessorDAO().getById(profID);
				
			if (prof == null) {
				throw new RuntimeException("Professor with professor_id = " + profID + " is not found!");
			}

			List<Exam> ex_list = (List<Exam>) FactoryDAO.getExamDAO().getExamByProf(prof);
			if (ex_list != null && ex_list.size() > 0) {
				JSONArray list = new JSONArray();
				for (Exam e : ex_list) {
					list.add(e.kJSON());
				}

				String result = list.toString();
				return result;
			} else {
				// return empty JSON array, because professor doesn't have any exams
				return new JSONArray().toString();
			}
		} catch (Exception e) {
			LOG.error("Error: ", e);
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));

			return obj.toString();
		}
	}
	
	/**
	 * Get professor by university.
	 * 
	 * @param String
	 *            param: univ_id
	 *            
	 * @return 	 
	 *  JSONArray of JSONObject in format:
	 * "prof_id" 			: "value",
	 * "first_name" 			: "value",
	 * "patronymic" 			: "value",
	 * "last_name" 			: "value",
	 * "birthday" 			: "value",
	 * "note" 			: "value",
	 * "univ_id" 			: "value",
	 * "univ_name" 			: "value",
	 * "city" 			: "value",
	 * 
	 * In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String getProfsByUniversity(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getProfsByUniversity' called with parameters = " + param);
		}
		
		try {
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"univ_id"});
			
			Long univID = Long.parseLong(inputParams.get("univ_id"));
				
			Collection<Professor> prof = FactoryDAO.getProfessorDAO().getProfByUniversity(univID);
			if(prof != null && prof.size() > 0) {
				JSONArray list = new JSONArray();
				for(Professor p : prof) {
					list.add(p.kJSON());
				}	
				String result = list.toString();
				
				return result;
			} else {
				// return empty JSON array, because subject doesn't have any exams
				return new JSONArray().toString();
			}
		} catch (Exception e) {
			LOG.error("Error: ", e);
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
			return obj.toString();
		}
	}
	
	/**
	 * Get faculties by university.
	 * 
	 * @param String
	 *            param: univ_id
	 *            
	 * @return 	 
	 *  JSONArray of JSONObject in format:
	 * "faculty_id" 			: "value",
	 * "faculty_name" 			: "value",
	 * "univ_id" 			: "value",
	 * "univ_name" 			: "value",
	 * "city" 			: "value"
	 * 
	 * In case of errors: JSONObject in format: "error" :
	 *         "error_message", "stacktrace" : "error_stacktrace";
	 * */
	public String getFacultiesByUniversity (String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getProfsByUniversity' called with parameters = " + param);
		}
		
		try {
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"univ_id"});
			
			Long univID = Long.parseLong(inputParams.get("univ_id"));
				
			Collection<Faculty> faculty = FactoryDAO.getFacultyDAO().getFacultiesByUniversity(univID);
			if(faculty != null && faculty.size() > 0) {
				JSONArray list = new JSONArray();
				for(Faculty f : faculty) {
					list.add(f.kJSON());
				}	
				String result = list.toString();
				
				return result;
			} else {
				// return empty JSON array, because subject doesn't have any exams
				return new JSONArray().toString();
			}
		} catch (Exception e) {
			LOG.error("Error: ", e);
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
			return obj.toString();
		}
	}
}
